package com.zjcode.cdcer.service.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import com.chinatechstar.component.commons.entity.MPage;
import com.chinatechstar.component.commons.result.PaginationBuilder;
import com.chinatechstar.component.commons.service.AliyunOssService;
import com.chinatechstar.component.commons.service.BaseService;
import com.chinatechstar.component.commons.supports.PageData;
import com.chinatechstar.component.commons.utils.ExcelUtils;
import com.chinatechstar.component.commons.utils.StringUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.zjcode.cdcer.mapper.*;
import com.zjcode.cdcer.model.*;
import com.zjcode.cdcer.model.basic.JsonObj;
import com.zjcode.cdcer.model.excel.SysteminitImportInfo;
import com.zjcode.cdcer.pojo.CerSysteminitImportInfo;
import com.zjcode.cdcer.service.*;
import com.zjcode.cdcer.utils.Utils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author ZQM
 * @date 2023/10/9 15:01
 */
@Service
public class FollowUpListOfficeServiceImpl implements FollowUpListOfficeService, BaseService {

    @Autowired
    private CerSysteminitImportInfoMapper cerSysteminitImportInfoMapper;

    @Autowired
    private FollowUpListOfficeMapper followUpListOfficeMapper;

    @Autowired
    private FollowUpListMapper followUpListMapper;

    @Autowired
    private TkmSysOrgMapper orgMapper;

    @Autowired
    private TkmSysUserMapper userMapper;

    @Autowired
    private SysUserService sysUserService;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private FollowUpListService followUpListService;

    @Autowired
    private CerSysteminitImportInfoService cerSysteminitImportInfoService;

    @Value("${studio.cer-personinfo-file-in-disk}")
    private String cerPersonFileInDisk;

    @Autowired
    private AliyunOssService aliyunOssService;
    @Override
    public JsonObj add(PageData pageData) {
        Object data = pageData.get("data");
        if (data == null) {
            return JsonObj.error("要存入的数据不存在");
        }
        List<String> followUpListId = Arrays.asList(String.valueOf(data).split("\\|"));
        int successCount = 0;
        int failCount = 0;
        // 随访列表正式库数据添加
        if (StringUtils.isNotEmpty(followUpListId)) {
            for (String item : followUpListId) {
                // 随访列表查询
                ZjcodeFollowUpList followUpList = followUpListMapper.selById(item);
                if (followUpList.getQualified().equals(1)) {
                    // 数据上报信息查询
                    CerSysteminitImportInfo cerSysteminitImportInfo = cerSysteminitImportInfoMapper.selInfoById(followUpList.getCerSysteminitImportInfoId());
                    // 流行病随访信息查询
                    ZjcodeFollowUpEpidemic epidemic = followUpListMapper.selEpidemicByFollowUpId(followUpList.getId());
                    // 随访情况查询
                    List<ZjcodeFollowUpCondition> conditionList = followUpListMapper.selConditionByFollowUpId(followUpList.getId());
                    ZjcodeFollowUpListOffice follow = new ZjcodeFollowUpListOffice() {{
                        setId(get32UUID());
                        setFollowUpListId(followUpList.getId());
                        setCerSysteminitImportInfoId(cerSysteminitImportInfo.getId());
                        setContact(epidemic.getContact());
                        setTreat(epidemic.getTreat());
                        setNotice(epidemic.getNotice());
                        setDeathTime(epidemic.getDeathTime());
                        setDeathCause(epidemic.getDeathCause());
                        setIcd10(epidemic.getIcd10());
                        setLoseFollowUpCause(epidemic.getLoseFollowUpCause());
                        setCountrySource("2");
                    }};

                    followUpListOfficeMapper.add(follow);

                    // 随访情况正式库数据添加
                    if (StringUtils.isNotEmpty(conditionList)) {
                        List<ZjcodeFollowUpConditionOffice> followUpConditionList = new ArrayList<>();
                        conditionList.forEach(condition -> {
                            ZjcodeFollowUpConditionOffice followUpCondition = new ZjcodeFollowUpConditionOffice() {{
                                setId(get32UUID());
                                setFollowUpListOfficeId(follow.getId());
                                setNumber(condition.getNumber());
                                setPlanTime(condition.getPlanTime());
                                setActualTime(condition.getActualTime());
                                setEsophagus(condition.getEsophagus());
                                setCardia(condition.getCardia());
                                setStomach(condition.getStomach());
                                setDuodenum(condition.getDuodenum());
                            }};
                            followUpConditionList.add(followUpCondition);
                        });
                        followUpListOfficeMapper.addFollowUpOffice(followUpConditionList);
                    }

                    // 修改随访列表上报状态
                    Integer i = followUpListMapper.uploadedReported(item);
                    if (i > 0) {
                        successCount++;
                    } else {
                        failCount++;
                    }
                } else {
                    failCount++;
                }
            }
        } else {
            return JsonObj.error("要存入的数据不存在");
        }
        return JsonObj.success("成功存入" + successCount + "条数据，" + failCount + "条失败");
    }

    @Override
    public Map<String, Object> selList(PageData pageData) {
        // 获取当前用户信息
        Long userId = Long.valueOf(pageData.get("user").toString());
        TkmSysUser userInfo = userMapper.selectByPrimaryKey(userId);
        TkmSysOrg orgInfo = orgMapper.selectByPrimaryKey(userInfo.getOrgId());
        pageData.put("ancestors", orgInfo.getAncestors().replace(",", "|"));
        // 解析分页参数
        MPage mPage = getPageInfo(pageData);
        Page<Object> page = PageHelper.startPage(mPage.getCurrentPage(), mPage.getPageSize());
        List<LinkedHashMap<String, Object>> list = followUpListOfficeMapper.selList(pageData);
        return PaginationBuilder.buildResult(list,
                page.getTotal(),
                mPage.getCurrentPage(),
                mPage.getPageSize());
    }

    @Override
    public JsonObj selById(String id) {
        Map<String, Object> map = followUpListOfficeMapper.selById(id);
        List<ZjcodeFollowUpConditionOffice> followUpConditionOfficeList = followUpListOfficeMapper.selConditionByFollowUpListOfficeId((String) map.get("id"));
        map.put("followUpConditionOfficeList", followUpConditionOfficeList);
        return JsonObj.success(map);
    }

    @Override
    public JsonObj followUpListOfficeReturn(PageData pageData) {
        String id = (String) pageData.get("id");
        // 随访正式库数据退回
        followUpListOfficeMapper.followUpListOfficeReturn(id);
        // 随访情况正式库数据退回
        followUpListOfficeMapper.followUpListConditionOfficeReturn(id);
        // 随访列表数据库恢复，5退回
        pageData.put("qualified", 5);
        followUpListMapper.uploadedRecover(pageData);
        return JsonObj.success("退回成功");
    }

    @Override
    public List<LinkedHashMap<String, Object>> queryAllExportData(PageData pageData) {
        String userId = (String) pageData.get("user");
        Object idsData = pageData.get("ids");
        if (idsData==null) {
            return new ArrayList<>();
        }
        // 获取extFlag
        String extFlag = sysUserService.findUserExtFlag(userId);
        List<String> ids = Arrays.asList(String.valueOf(idsData).split("\\|"));
        List<LinkedHashMap<String, Object>> list = followUpListOfficeMapper.queryAllExportData(extFlag, ids, pageData,idsData);
        // 查询数据自定并分组
        List<SysDict> allCerDicts = sysDictService.findAllCerDicts();
        Map<String, List<SysDict>> keyListMap = allCerDicts
                .stream()
                .collect(Collectors.groupingBy(SysDict::getDictType));
        keyListMap.entrySet().parallelStream().forEach(entry -> {
            // key
            String key = entry.getKey();
            List<SysDict> dicts = entry.getValue();
            list.parallelStream().forEach(item->{
                Object o = item.get(key);
                if (o!=null) {
                    Optional<SysDict> first = dicts.stream()
                            .filter(sysDict -> sysDict.getDictValue().equals(o.toString())).findFirst();
                    first.ifPresent(sysDict -> {
                        item.put(key, sysDict.getDictName());
                    });
                }
            });
        });
        return list;
    }

    /**
     * 随访正式库导入国家数据结构业务分析：
     * 1、先判断screening_id有没有  --  判断人员信息表或初始临时表存不存在该值
     *  => 1.1、没有，报错、“初始上报和初始正式库都没有该人员信息”
     *     1.2、 有，先判断正式库存不存在该值，（1）存在，报错，提示“正式库已存在”
     *     （2）不存在，查随访列表是否存在，① 不存在，补充随访列表数据和随访正式库相应数据 ②存在，增加随访正式库数据
     * @param file
     * @param response
     * @param userId
     * @return
     */
    @Override
    public JsonObj importGJData(MultipartFile file, HttpServletResponse response, String userId) {
        ImportParams params = new ImportParams();
        params.setTitleRows(0);
        File tmpfile =cerSysteminitImportInfoService.commonImportConfig(file,userId);
        // 解析excel
        List<SysteminitImportInfo> list = ExcelImportUtil.importExcel(tmpfile, SysteminitImportInfo.class, params);
        // 数据过滤,国家来源的数据默认都是正确的，仅过滤名称为null的
        list = list.stream().filter(each -> StringUtils.isNotEmpty(each.getName()) && !Objects.equals("测试",each.getName())).collect(Collectors.toList());
        int count = 0;
        // 执行数据写入
        List<LinkedHashMap<String, Object>> failList =new ArrayList<>();
        if (list.size() > 0) {
            // 查初始上报临时表中screeningId不为空的list
            List<CerSysteminitImportInfo> infos=cerSysteminitImportInfoService.getAllInitImports();
            // 成功的数据（过滤 errorFlag == 1成功），批量新增
            List<SysteminitImportInfo> successList=new ArrayList<>();
            list.forEach(item->{
                item.setErrorMsg("初始上报和初始正式库没有该人员信息，需要先上报，才能进行随访或治疗操作");
                item.setErrorFlag(2);
                infos.forEach(each->{
                    if (Objects.equals(item.getScreeningId(),each.getScreeningId())) {
                        item.setErrorMsg("随访正式库中，已存在该人员的随访数据");
                        String initId = each.getId();
                        if (getOfficalCountByInitId(initId) == 0){
                            SysteminitImportInfo systeminitImportInfo =new SysteminitImportInfo();
                            BeanUtils.copyProperties(item,systeminitImportInfo);
                            systeminitImportInfo.setErrorFlag(1);
                            systeminitImportInfo.setInitId(initId);
                            successList.add(systeminitImportInfo);
                        }
                    }
                });
            });
            // 失败列表
            list.stream().filter(each -> each.getErrorFlag()== 2 ).forEach(item ->{
                failList.add(cerSysteminitImportInfoService.getLinkedMapByList(item, item.getErrorMsg() ));
            });
            // 成功数据
            if (CollectionUtils.isNotEmpty(successList)) {
                List<String> initIds = successList.stream().map(SysteminitImportInfo::getInitId).collect(Collectors.toList());
                List<ZjcodeFollowUpList> tempList=followUpListMapper.getUpListByInitId(initIds);
                List<String> upListIds=new ArrayList<>();
                successList.forEach(item->{
                    tempList.forEach(each->{
                        if (Objects.equals(each.getCerSysteminitImportInfoId(),item.getInitId())) {
                            // 随访列表存在，但是随访正式库不存在：【临时状态：3；其他情况是1】
                            item.setErrorFlag(3);
                            item.setFollowUpListId(each.getId());
                        }
                    });
                });
                for (SysteminitImportInfo info : successList) {
                    // 查随访列表是否存在，① 不存在，补充随访列表数据和随访正式库相应数据 ②存在，增加随访正式库数据
                    String initId = info.getInitId();
                    if (info.getErrorFlag() == 1) {
                        // 说明：随访列表不存在，且随访正式库不存在
                        // 随访次数
                        String number = info.getNumber();
                        ZjcodeFollowUpList zjcodeFollowUpList=new ZjcodeFollowUpList();
                        String id =get32UUID();
                        zjcodeFollowUpList.setId(id);
                        zjcodeFollowUpList.setCerSysteminitImportInfoId(initId);
                        zjcodeFollowUpList.setErrorMessage(followUpListService.dataValidation(null).toString());
                        zjcodeFollowUpList.setQualified(2);
                        zjcodeFollowUpList.setIsUploaded(1);//1已上报
                        // 新增随访列表
                        followUpListMapper.addUpList(zjcodeFollowUpList);
                        String officalId = get32UUID();
                        // 随访正式库
                        count += followUpListOfficeMapper.add(new ZjcodeFollowUpListOffice(){{
                            setId(get32UUID());setFollowUpListId(id); setCerSysteminitImportInfoId(initId);setCountrySource("1");
                        }});
                        if (!ObjectUtils.isEmpty(number)) {
                            //如果随访次数不为null，需新增相应条数的随访情况
                            List<ZjcodeFollowUpCondition> followUpConditionList =new ArrayList<>();
                            for (int i = 1; i <= Integer.parseInt(number); i++) {
                                ZjcodeFollowUpCondition condition=new ZjcodeFollowUpCondition();
                                condition.setId(get32UUID());
                                condition.setFollowUpListId(id);
                                condition.setNumber(i);
                                ZjcodeFollowUpConditionOffice conditionOffice =new ZjcodeFollowUpConditionOffice();
                                conditionOffice.setId(get32UUID());
                                conditionOffice.setFollowUpListOfficeId(officalId);
                                conditionOffice.setNumber(i);
                                condition.setZjcodeFollowUpConditionOffice(conditionOffice);
                                followUpConditionList.add(condition);
                            }
                            followUpListMapper.addCondition(followUpConditionList);
                            // 随访正式库的随访情况
                            followUpListOfficeMapper.addFollowUpOfficeCondition(followUpConditionList);
                        }
                    }else {
                        // 说明：随访列表存在，但是随访正式库不存在
                        String followUpListId = info.getFollowUpListId();
                        upListIds.add(followUpListId);
                        String officalId = get32UUID();
                        // 流行病随访信息查询
                        ZjcodeFollowUpEpidemic epidemic = followUpListMapper.selEpidemicByFollowUpId(followUpListId);
                        // 新增随访正式表
                        count += followUpListOfficeMapper.add(new ZjcodeFollowUpListOffice(){{
                            setId(officalId); setFollowUpListId(followUpListId); setCerSysteminitImportInfoId(initId);
                            setContact(epidemic.getContact()); setTreat(epidemic.getTreat()); setNotice(epidemic.getNotice());
                            setDeathTime(epidemic.getDeathTime()); setDeathCause(epidemic.getDeathCause()); setIcd10(epidemic.getIcd10());
                            setLoseFollowUpCause(epidemic.getLoseFollowUpCause());setCountrySource("1");
                        }});
                        List<ZjcodeFollowUpCondition> conditionOfficeList = followUpListMapper.selConditionByFollowUpId(followUpListId);
                        if (CollectionUtils.isNotEmpty(conditionOfficeList)) {
                            conditionOfficeList.forEach(offical ->{
                                ZjcodeFollowUpConditionOffice conditionOffice =new ZjcodeFollowUpConditionOffice();
                                conditionOffice.setId(get32UUID());
                                conditionOffice.setFollowUpListOfficeId(officalId);
                                conditionOffice.setNumber(offical.getNumber());
                                offical.setZjcodeFollowUpConditionOffice(conditionOffice);
                            });
                            // 随访正式库的随访情况
                            followUpListOfficeMapper.addFollowUpOfficeCondition(conditionOfficeList);
                        }
                    }
                }
                // 最后，把随访列表逻辑删除
                Integer numberDel = CollectionUtils.isNotEmpty(upListIds) ? followUpListMapper.updateFollowUpListStatusByIds(upListIds) : null;
            }
        }
        // 组装表头
        List<String> headList = Arrays.asList(
                "省份",
                "城市",
                "区县",
                "乡镇",
                "村",
                "机构名称",
                "调查对象ID号",
                "姓名",
                "性别",
//                "筛查类型",
                "生日",
                "民族",
                "身份证号",
                "地址",
                "联系电话",
                "筛查类型",
                "随访次数",
                "内镜号",
                "是否无痛",
                "染色类别",
                "是否活检",
                "内镜诊疗日期",
                "Hp",
                "Hp检测方法",
                "图片数量",
                "内镜诊断",
                "内镜诊断医师",
                "内镜审核医师",
                "病理号",
                "病理报告日期",
                "食管病理诊断代码",
                "贲门病理诊断代码",
                "胃病理诊断代码",
                "十二指肠病理诊断代码",
                "病理诊断医师",
                "病理审核医师",
                "病理诊断",
                "导入错误原因");
        try {
            // 导出
            if (CollectionUtils.isNotEmpty(failList)) {
//                String s = ExcelUtils.downloadExcel(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                File downloadExcelFile = ExcelUtils.downloadExcelFile(headList, failList, "导入失败数据导出", response, cerPersonFileInDisk);
                String upload = aliyunOssService.upload(downloadExcelFile);
                HashMap<String,Object> res =new HashMap<>();
                res.put("errorFile", upload);
                String msg ="导入失败"+failList.size()+"条";
                if (count>0) {
                    msg += "，导入成功"+count+"条数据";
                }
                return JsonObj.success(res,msg);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonObj.error("错误数据导出失败");
        }
        return JsonObj.success("导入成功"+count+"条数据");
    }

    private int getOfficalCountByInitId(String initId) {
        return followUpListOfficeMapper.getOfficalCountByInitId(initId);
    }

}
